"""
@Author: li
@Email: lijianqiao2906@live.com
@FileName: password_validator.py
@DateTime: 2025/07/16 00:00:00
@Docs: 密码验证和加密工具
"""

import re
from datetime import datetime

from app.utils.logger import logger
from app.utils.password_encryption import decrypt_password, encrypt_password


class PasswordValidator:
    """密码验证器"""

    def __init__(self):
        self.min_length = 8
        self.max_length = 128
        self.require_uppercase = True
        self.require_lowercase = True
        self.require_digits = True
        self.require_special = True

    def validate_password_strength(self, password: str) -> dict:
        """
        验证密码强度

        Args:
            password: 待验证的密码

        Returns:
            验证结果字典
        """
        errors = []

        if len(password) < self.min_length:
            errors.append(f"密码长度至少为{self.min_length}位")

        if len(password) > self.max_length:
            errors.append(f"密码长度不能超过{self.max_length}位")

        if self.require_uppercase and not re.search(r"[A-Z]", password):
            errors.append("密码必须包含大写字母")

        if self.require_lowercase and not re.search(r"[a-z]", password):
            errors.append("密码必须包含小写字母")

        if self.require_digits and not re.search(r"\d", password):
            errors.append("密码必须包含数字")

        if self.require_special and not re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
            errors.append("密码必须包含特殊字符")

        is_valid = len(errors) == 0

        return {"is_valid": is_valid, "errors": errors, "strength": self._calculate_strength(password)}

    def _calculate_strength(self, password: str) -> str:
        """计算密码强度等级"""
        score = 0

        if len(password) >= 8:
            score += 1
        if len(password) >= 12:
            score += 1
        if re.search(r"[a-z]", password):
            score += 1
        if re.search(r"[A-Z]", password):
            score += 1
        if re.search(r"\d", password):
            score += 1
        if re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
            score += 1

        if score <= 2:
            return "weak"
        elif score <= 4:
            return "medium"
        else:
            return "strong"

    def encrypt_and_validate(self, password: str) -> tuple[str, bool]:
        """
        加密并验证密码

        Args:
            password: 明文密码

        Returns:
            (加密后的密码, 是否验证成功)
        """
        validation_result = self.validate_password_strength(password)

        if not validation_result["is_valid"]:
            logger.warning(f"密码验证失败: {validation_result['errors']}")
            return "", False

        try:
            encrypted = encrypt_password(password)
            logger.info("密码加密成功")
            return encrypted, True
        except Exception as e:
            logger.error(f"密码加密失败: {e}")
            return "", False

    def decrypt_and_validate(self, encrypted_password: str) -> tuple[str, bool]:
        """
        解密并验证密码

        Args:
            encrypted_password: 加密的密码

        Returns:
            (解密后的密码, 是否验证成功)
        """
        try:
            decrypted = decrypt_password(encrypted_password)
            return decrypted, True
        except Exception as e:
            logger.error(f"密码解密失败: {e}")
            return "", False

    def is_password_expired(self, last_updated: datetime | None, days: int = 90) -> bool:
        """
        检查密码是否过期

        Args:
            last_updated: 密码最后更新时间
            days: 过期天数

        Returns:
            是否过期
        """
        if not last_updated:
            return True

        from datetime import timedelta

        return datetime.now() - last_updated > timedelta(days=days)


# 全局密码验证器实例
password_validator = PasswordValidator()
